/*
* Copyright (c) 2016 ShopJsp. All Rights Reserved.
 * ============================================================================
 * 版权所有 2011 - 今 北京华宇盈通科技有限公司，并保留所有权利。
 * ----------------------------------------------------------------------------
 * 提示：在未取得SHOPJSP商业授权之前，您不能将本软件应用于商业用途，否则SHOPJSP将保留追究的权力。
 * ----------------------------------------------------------------------------
 * 官方网站：http://www.shopjsp.com
 * ============================================================================
*/
package com.hyyt.shopjsp.util.redis.dao.impl;

import com.hyyt.shopjsp.util.redis.dao.IRedisBasicDao;
import org.apache.log4j.Logger;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Redis 基础Dao实现类
 *
 * @author ankang
 */
@Repository("redisBasicDao")
public class RedisBasicDao implements IRedisBasicDao {
    private static final Logger logger = Logger.getLogger(RedisBasicDao.class);
    /**
     * 注入redisTemplate
     **/
    @Resource
    private StringRedisTemplate redisTemplate;

    /**
     * 向Redis中添加值
     *
     * @param key
     * @param value
     */
    public void setKey(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
        logger.debug(new StringBuilder().append("添加redis->").append(" key  : ").append(key).append(" value : ").append(value).toString());
    }

    /**
     * 向Redis中添加值
     *
     * @param key
     * @param value
     * @param liveTime
     */
    @Override
    public void setKey(String key, String value, long liveTime) {
        redisTemplate.opsForValue().set(key, value, liveTime,TimeUnit.SECONDS);
        logger.debug(new StringBuilder().append("添加redis->").append(" key  : ").append(key).append(" value : ").append(value).append("有效期：" + liveTime).toString());
    }

    /**
     * 增加到zeset缓存
     *
     * @param key
     * @param value
     * @param score
     */
    @Override
    public Boolean addToZset(String key, String value, Long score) {
        //
        Boolean result = redisTemplate.opsForZSet().add(key, value, score);
        logger.info(new StringBuilder().append("添加ZSET->")
                .append(" key  : ")
                .append(key)
                .append(" value : ").append(value)
                .append("  结果为: ---->")
                .append(result).toString());
        return result;
    }

    /**
     * 设置redis的失效时间
     *
     * @param key
     * @param timout
     * @param timeUnit
     */
    @Override
    public Boolean expire(String key, long timout, TimeUnit timeUnit) {
        //
        Boolean result = redisTemplate.expire(key, timout, timeUnit);
        logger.debug(new StringBuilder().
                append("设置失效时间->")
                .append(" key  : ")
                .append(key)
                .append(" timout : ").append(timout)
                .append("  结果为: ---->")
                .append(result).toString());
        return result;
    }

    /**
     * 删除Zset中的元素，用于控制队列大小
     *
     * @param key
     * @param start
     * @param end
     */
    @Override
    public Long removeZsetRange(String key, long start, long end) {
        Long result = redisTemplate.opsForZSet().removeRange(key, start, end);
        logger.debug(new StringBuilder().
                append("从zset中移除元素->")
                .append(" key  : ")
                .append(key)
                .append(" start : ").append(start)
                .append(" end : ").append(end)
                .append("  结果为: ---->")
                .append(result).toString());
        return result;
    }

    /**
     * 从zset缓存中移除
     *
     * @param key
     * @param value
     */
    @Override
    public Long removeFromZset(String key, String value) {
        Long result = redisTemplate.opsForZSet().remove(key, value);
        logger.info(new StringBuilder().
                append("从zset中移除元素->")
                .append(" key  : ")
                .append(key)
                .append(" value : ").append(value)
                .append("  结果为: ---->")
                .append(result).toString());
        return result;
    }

    /**
     * 从redis中删除某个key
     *
     * @param key
     */
    @Override
    public void deleteByKey(String key) {
        redisTemplate.opsForValue().getOperations().delete(key);
        logger.info(new StringBuilder().
                append("从redis中删除指定键")
                .append(" key  : ")
                .append(key)
                .toString());
    }

    /**
     * redis计数
     *
     * @param key
     * @param increment
     */
    @Override
    public void increment(String key, Integer increment) {
        Long result = redisTemplate.opsForValue().increment(key, increment);
        logger.debug(new StringBuilder().
                append("自动计数->")
                .append(" key  : ")
                .append(key)
                .append(" 增加了 :  ")
                .append(increment)
                .append(" 结果为  :  ")
                .append(result)
                .toString());
    }

    /**
     * 从Redis中根据key获取
     *
     * @param key
     * @return
     */
    @Override
    public String getValue(String key) {
        String result = redisTemplate.opsForValue().get(key);
        logger.debug(new StringBuilder().append("获取键值->")
                .append(" key  : ")
                .append(key)
                .append(" result : ")
                .append(result)
                .toString());

        return result;
    }

    /**
     * 设置token
     *
     * @param key
     * @param value
     * @return
     */
    @Override
    public void setToken2Rredis(String key, String value) {
        redisTemplate.opsForValue().set(key, value, 1, TimeUnit.DAYS);
        logger.debug(new StringBuilder().append("设置token->")
                .append(" key  : ")
                .append(key)
                .append(" value  : ")
                .append(value)
                .toString());
    }

    /**
     * 从Zset中分页查询,按照分数从大到小排列
     *
     * @param key
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public List<String> getPageFromZsetByScoreDesc(String key, int pageNum, int pageSize) {
        if (pageNum < 1) pageNum = 1;
        if (pageSize < 1) pageSize = 1;
        if (pageSize > 20) {
            pageSize = 20;
        }
        int start = (pageNum - 1) * pageSize;
        int end = start + pageSize - 1;
        List<String> idList = new ArrayList<>();

        Set<String> result = redisTemplate.opsForZSet().reverseRange(key, start, end);
        for (String id : result) {
            idList.add(id);
        }
        logger.debug(new StringBuilder().append("ZSet中分页查询")
                .append(" key  : ")
                .append(key)
                .append(" pageNum  : ")
                .append(pageNum)
                .append(" pageSize  : ")
                .append(pageSize)
                .append(" result : ")
                .append(result)
                .toString());

        return idList;
    }

    /**
     * 从Zset中查询全部
     *
     * @param key
     * @return
     */
    @Override
    public List<String> getAllFromZset(String key) {
        List<String> idList = new ArrayList<>();

        Set<String> result = redisTemplate.opsForZSet().range(key, 0, -1);
        for (String id : result) {
            idList.add(id);
        }
        logger.debug(new StringBuilder().append("ZSet中查询全部")
                .append(" key  : ")
                .append(key)
                .append(" result : ")
                .append(result)
                .toString());
        return idList;
    }

    /**
     * 获取zset中的分数值
     *
     * @param zsetKey
     * @param value
     * @return
     */
    @Override
    public Double score(String zsetKey, String value) {
        Double score = redisTemplate.opsForZSet().score(zsetKey, value);
        logger.debug(new StringBuilder().
                append("查询分数")
                .append(" zsetKey  : ")
                .append(zsetKey)
                .append(" zsetKey  : ")
                .append(zsetKey)
                .append(" score : ")
                .append(score)
                .toString());

        return score;
    }

    /**
     * 获取zset中的总数
     *
     * @param zsetKey
     * @return
     */
    @Override
    public Long zCard(String zsetKey) {
        Long count = redisTemplate.opsForZSet().zCard(zsetKey);
        logger.debug(new StringBuilder().
                append("查询总数")
                .append(" zsetKey  : ")
                .append(zsetKey)
                .append(" 总数 : ")
                .append(count)
                .toString());

        return count;
    }


    /**
     * 向Redis中添加Hash
     *
     * @param key
     * @param hashKey
     * @param hashValue
     */
    @Override
    public void putToHash(String key, String hashKey, String hashValue) {
        redisTemplate.opsForHash().put(key, hashKey, hashValue);
        logger.debug(new StringBuilder().append("添加Hash缓存").append(" key  : ").append(key).append(" HashKey : ")
                .append(hashKey).append(" HashValue : ").append(hashValue).append("  结果为: ---->").toString());
    }

    /**
     * 判断Hash中是否存在key
     *
     * @param key
     * @param hashKey
     * @return
     */
    @Override
    public Boolean isHashHasKey(String key, String hashKey) {
        Boolean b = redisTemplate.opsForHash().hasKey(key, hashKey);
        logger.debug(new StringBuilder().append("查询hashKey是否存在").append(" key  : ").append(key).append(" HashKey : ")
                .append(hashKey).toString());
        return b;
    }

    /**
     * 查询Hash中的全部值
     *
     * @param key
     * @return
     */
    @Override
    public Map getAllFromHash(String key) {
        Map map = redisTemplate.opsForHash().entries(key);
        logger.debug(new StringBuilder().append("查询Hash中的全部值").append(" key  : ").append(key).toString());
        return map;
    }

    /**
     * 从Hash中删除值
     *
     * @param key
     * @param hashKey
     */
    @Override
    public void deleteFromHash(String key, String hashKey) {
        redisTemplate.opsForHash().delete(key, hashKey);
        logger.debug(new StringBuilder().append("删除Hash中的值:").append(" key  : ").append(key).append(" HashKey : ")
                .append(hashKey).toString());
    }
}
